package re;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

/**
 * @author haoly
 * @title PatternTest
 * @date 2025/4/17 08:59
 * @description 正则表达式测试
 */
public class PatternTest {

    @Test
    void testToString() {
        Pattern pattern = new Repeat<>(
                new Choose<>(
                        new Concatenate(new Literal('a'), new Literal('b')),
                        new Literal('a')
                )
        );

        assertEquals("(ab|a)*", pattern.toString());
    }

    @Test
    void testMatches() {
        Pattern pattern = new Empty();
        assertFalse(pattern.matches("a"));

        Pattern aLiteral = new Literal('a');
        assertTrue(aLiteral.matches("a"));

    }

    @Test
    void testConcatenateMatches() {
        Pattern pattern = new Concatenate<>(
                new Literal('a'),
                new Literal('b')
        );
        assertEquals("ab", pattern.toString());
        assertFalse(pattern.matches("a"));
        assertTrue(pattern.matches("ab"));
        assertFalse(pattern.matches("abc"));

    }

    @Test
    void testChooseMatches() {
        Pattern pattern = new Choose<>(
                new Literal('a'),
                new Literal('b')
        );
        assertEquals("a|b", pattern.toString());
        assertTrue(pattern.matches("a"));
        assertTrue(pattern.matches("b"));
        assertFalse(pattern.matches("c"));

    }

    @Test
    void testRepeatMatches() {
        Pattern pattern = new Repeat<>(new Literal('a'));
        assertEquals("a*", pattern.toString());

        assertTrue(pattern.matches(""));
        assertTrue(pattern.matches("a"));
        assertTrue(pattern.matches("aaaa"));
        assertFalse(pattern.matches("b"));

    }

    @Test
    void testMixMatches() {
        Pattern pattern = new Repeat<>(
                new Concatenate<>(
                        new Literal('a'),
                        new Choose<>(new Empty(), new Literal('b'))
                )
        );



        assertEquals("(a(|b))*", pattern.toString());

        assertTrue(pattern.matches(""));
        assertTrue(pattern.matches("a"));
        assertTrue(pattern.matches("ab"));
        assertTrue(pattern.matches("aba"));
        assertTrue(pattern.matches("abab"));
        assertTrue(pattern.matches("abaab"));
        assertFalse(pattern.matches("abba"));

    }
}
